using BasicData.API.Dtos;
using Microsoft.Extensions.Caching.Memory;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Text;

namespace BasicData.API.Services
{
    /// <summary>
    /// 验证码服务实现
    /// </summary>
    public class CaptchaService : ICaptchaService
    {
        private readonly IMemoryCache _cache;
        private readonly ILogger<CaptchaService> _logger;
        private static readonly Random _random = new Random();
        private static readonly string _chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        private const string CAPTCHA_PREFIX = "captcha_";
        private const int DEFAULT_EXPIRE_MINUTES = 5;

        public CaptchaService(IMemoryCache cache, ILogger<CaptchaService> logger)
        {
            _cache = cache;
            _logger = logger;
        }

        /// <summary>
        /// 生成验证码
        /// </summary>
        public async Task<CaptchaGenerateResponse> GenerateCaptchaAsync(CaptchaGenerateRequest request)
        {
            try
            {
                // 限制参数范围
                request.Width = Math.Min(Math.Max(request.Width, 80), 400);
                request.Height = Math.Min(Math.Max(request.Height, 30), 200);
                request.Length = Math.Min(Math.Max(request.Length, 3), 8);
                
                // 生成随机验证码
                var captchaCode = GenerateRandomCode(request.Length);
                
                // 生成验证码图片
                var imageBase64 = await GenerateCaptchaImageBase64Async(captchaCode, request.Width, request.Height);
                
                // 生成唯一标识符
                var captchaId = Guid.NewGuid().ToString("N");
                
                // 将验证码存储到缓存中，设置过期时间
                var cacheKey = GetCacheKey(captchaId);
                var expireMinutes = request.ExpireMinutes > 0 ? request.ExpireMinutes : DEFAULT_EXPIRE_MINUTES;
                _cache.Set(cacheKey, captchaCode.ToUpper(), TimeSpan.FromMinutes(expireMinutes));

                _logger.LogInformation("验证码生成成功，ID: {CaptchaId}, 验证码: {Code}", captchaId, captchaCode);

                return new CaptchaGenerateResponse
                {
                    ImageBase64 = imageBase64,
                    CaptchaId = captchaId,
                    ExpireSeconds = expireMinutes * 60
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "生成验证码时发生错误");
                throw new InvalidOperationException("生成验证码失败", ex);
            }
        }

        /// <summary>
        /// 刷新验证码
        /// </summary>
        public async Task<CaptchaGenerateResponse> RefreshCaptchaAsync(string captchaId, CaptchaGenerateRequest request)
        {
            try
            {
                // 移除旧的验证码
                var oldCacheKey = GetCacheKey(captchaId);
                _cache.Remove(oldCacheKey);
                
                // 生成新的验证码
                return await GenerateCaptchaAsync(request);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "刷新验证码时发生错误");
                throw new InvalidOperationException("刷新验证码失败", ex);
            }
        }

        /// <summary>
        /// 验证验证码
        /// </summary>
        public Task<CaptchaVerifyResponse> VerifyCaptchaAsync(CaptchaVerifyRequest request)
        {
            try
            {
                if (string.IsNullOrEmpty(request.CaptchaId) || string.IsNullOrEmpty(request.CaptchaCode))
                {
                    return Task.FromResult(new CaptchaVerifyResponse
                    {
                        IsValid = false,
                        Message = "验证码ID或验证码不能为空"
                    });
                }
                
                var cacheKey = GetCacheKey(request.CaptchaId);
                
                // 从缓存中获取验证码
                if (!_cache.TryGetValue(cacheKey, out string? storedCaptcha) || storedCaptcha == null)
                {
                    return Task.FromResult(new CaptchaVerifyResponse
                    {
                        IsValid = false,
                        Message = "验证码已过期或不存在"
                    });
                }

                // 验证用户输入的验证码
                var isValid = string.Equals(storedCaptcha, request.CaptchaCode.ToUpper(), StringComparison.OrdinalIgnoreCase);
                
                if (isValid)
                {
                    // 验证成功后从缓存中移除
                    _cache.Remove(cacheKey);
                    _logger.LogInformation("验证码验证成功，ID: {CaptchaId}", request.CaptchaId);
                }
                else
                {
                    _logger.LogWarning("验证码验证失败，ID: {CaptchaId}, 输入: {Input}, 正确: {Correct}", 
                        request.CaptchaId, request.CaptchaCode, storedCaptcha);
                }

                return Task.FromResult(new CaptchaVerifyResponse
                {
                    IsValid = isValid,
                    Message = isValid ? "验证码验证成功" : "验证码错误"
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "验证验证码时发生错误");
                return Task.FromResult(new CaptchaVerifyResponse
                {
                    IsValid = false,
                    Message = $"验证码验证失败: {ex.Message}"
                });
            }
        }

        /// <summary>
        /// 获取缓存键
        /// </summary>
        private string GetCacheKey(string captchaId)
        {
            return $"{CAPTCHA_PREFIX}{captchaId}";
        }

        /// <summary>
        /// 生成随机验证码
        /// </summary>
        private static string GenerateRandomCode(int length)
        {
            var result = new StringBuilder(length);
            for (int i = 0; i < length; i++)
            {
                result.Append(_chars[_random.Next(_chars.Length)]);
            }
            return result.ToString();
        }

        /// <summary>
        /// 生成验证码图片的Base64编码
        /// </summary>
        private async Task<string> GenerateCaptchaImageBase64Async(string code, int width, int height)
        {
            return await Task.Run(() =>
            {
                using var bitmap = new Bitmap(width, height);
                using var graphics = Graphics.FromImage(bitmap);
                
                // 设置高质量绘图
                graphics.SmoothingMode = SmoothingMode.AntiAlias;
                graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;

                // 绘制背景
                using var backgroundBrush = new LinearGradientBrush(
                    new Point(0, 0), 
                    new Point(width, height), 
                    Color.LightBlue, 
                    Color.White);
                graphics.FillRectangle(backgroundBrush, 0, 0, width, height);

                // 添加干扰线
                for (int i = 0; i < Math.Max(3, width / 40); i++)
                {
                    using var pen = new Pen(GetRandomColor(), 1);
                    var x1 = _random.Next(width);
                    var y1 = _random.Next(height);
                    var x2 = _random.Next(width);
                    var y2 = _random.Next(height);
                    graphics.DrawLine(pen, x1, y1, x2, y2);
                }

                // 添加干扰点
                for (int i = 0; i < Math.Max(50, width * height / 100); i++)
                {
                    using var brush = new SolidBrush(GetRandomColor());
                    var x = _random.Next(width);
                    var y = _random.Next(height);
                    graphics.FillEllipse(brush, x, y, 2, 2);
                }

                // 计算字体大小
                var fontSize = Math.Min(width / (code.Length + 1), height - 10);
                using var font = new Font("Arial", fontSize, FontStyle.Bold);

                // 绘制验证码文字
                var textSize = graphics.MeasureString(code, font);
                var textX = (width - textSize.Width) / 2;
                var textY = (height - textSize.Height) / 2;

                // 为每个字符添加随机颜色和位置偏移
                for (int i = 0; i < code.Length; i++)
                {
                    using var brush = new SolidBrush(GetRandomColor(50, 100));
                    var charX = textX + (textSize.Width / code.Length) * i;
                    var charY = textY + _random.Next(-5, 6);
                    
                    // 添加字符旋转
                    var rotationAngle = _random.Next(-15, 15);
                    graphics.TranslateTransform(charX + fontSize / 2, charY + fontSize / 2);
                    graphics.RotateTransform(rotationAngle);
                    graphics.DrawString(code[i].ToString(), font, brush, -fontSize / 2, -fontSize / 2);
                    graphics.ResetTransform();
                }

                // 转换为Base64字符串
                using var memoryStream = new MemoryStream();
                bitmap.Save(memoryStream, ImageFormat.Png);
                byte[] imageBytes = memoryStream.ToArray();
                return $"data:image/png;base64,{Convert.ToBase64String(imageBytes)}";
            });
        }

        /// <summary>
        /// 获取随机颜色
        /// </summary>
        private static Color GetRandomColor(int minBrightness = 50, int maxBrightness = 200)
        {
            return Color.FromArgb(
                _random.Next(minBrightness, maxBrightness), 
                _random.Next(minBrightness, maxBrightness), 
                _random.Next(minBrightness, maxBrightness));
        }
    }
} 